﻿namespace Aldart.WebSockets.Server
{
    using System;
    using System.Net;
    using System.Net.Sockets;

    /// <summary>
    /// Class used for serving WebSockets requests on a specified port.
    /// </summary>
    public class Server
    {
        /// <summary>
        /// Used to listen for incoming connections.
        /// </summary>
        private TcpListener listener;

        /// <summary>
        /// Initializes a new instance of the Server class.
        /// </summary>
        /// <param name="port">Port on which the server is listening</param>
        public Server(int port) {
            this.listener = new TcpListener(IPAddress.Any, port);
        }

        /// <summary>
        /// This event is raised every time a new client connects to the server. 
        /// </summary>
        /// <remarks>
        /// It is raised after the handshake is complete and successful. <para /> 
        /// This event is not synchronized,
        /// so raised events may come from different threads, but will come in the order in which they 
        /// were received.
        /// </remarks>
        public event EventHandler<ClientEventArgs> ClientConnect;

        /// <summary>
        /// This event is raised every time a message is received from a client.
        /// </summary>
        /// <remarks>
        /// The same effect could be gained from registering an event handler on ClientConnect and subscribing
        /// to the Message-event of the new client. <para />
        /// This event is not synchronized, so raised events may come from different threads, 
        /// but will come in the order in which they were received.
        /// </remarks>
        /// <seealso cref="Aldart.WebSockets.Server.Client.Message"/>
        public event EventHandler<ClientMessageEventArgs> ClientMessage;

        /// <summary>
        /// This event is raised every time a client disconnects.
        /// </summary>
        /// <remarks>
        /// The same effect could be gained from registering an event handler on ClientConnect and subscribing
        /// to the Disconnect-event of the new client.<para />
        /// This event is not synchronized, so raised events may come from different threads, 
        /// but will come in the order in which they were received.
        /// </remarks>
        /// <seealso cref="Aldart.WebSockets.Server.Client.Disconnect"/>
        public event EventHandler<ClientMessageEventArgs> ClientDisconnect;

        /// <summary>
        /// Starts the server, listening on the specified port.
        /// </summary>
        public void Start() {
            this.listener.Start();
            this.listener.BeginAcceptTcpClient(new AsyncCallback(this.AcceptTcpClient), null);
        }

        /// <summary>
        /// Stops the server.
        /// </summary>
        /// <remarks>
        /// No new clients will be accepted and current connections will be closed gracefully.
        /// </remarks>
        public void Stop() {
        }

        /// <summary>
        /// Called when the TcpListener accepts a new connection.
        /// </summary>
        /// <param name="result">Result object provided by the framework.</param>
        private void AcceptTcpClient(IAsyncResult result) {
            // Accept connection and start listening for the next one
            TcpClient client = this.listener.EndAcceptTcpClient(result);
            this.listener.BeginAcceptTcpClient(new AsyncCallback(this.AcceptTcpClient), null);
            
            // Start Handshake
        }
    }
}
